#include "embed.h"
#include <math.h>
#ifdef DEBUG
#include <stdio.h>
#endif
#include <stdlib.h>

//compute differences classification into a membership-bitmap
void diff_classification_all(
			     difference_class **m,
			     class_count *cc,
			     int **d,
			     unsigned char **a,
			     unsigned int h,
			     unsigned int w,
			     unsigned int t
			     )
{
  cc->n_EZ = cc->n_EN1 = cc->n_EN2 = cc->n_CH = cc->n_CHX = cc->n_NC = 0;
  int i, j, x, b;
  for(i=0; i<h; ++i)
    for(j=0; j<w; ++j) {
      x = MIN(2*(255 - a[i][j]), 2*a[i][j] + 1);
      b = d[i][j] >= 0;
      if(abs(2 * ((int)floor((float)d[i][j] / 2)) + b) <= x) {
	//is changeable
	if(abs(2 * d[i][j] + b) <= x) {
	  //is expandable
	  if(d[i][j] == 0 || d[i][j] == -1) {
	    //EZ
	    m[i][j] = EZ;
	    cc->n_EZ++;
	  }
	  else if(abs(d[i][j]) <= t) {
	    //EN1
	    m[i][j] = EN1;
	    cc->n_EN1++;
	  }
	  else {
	    //EN2
	    m[i][j] = EN2;
	    cc->n_EN2++;
	    if(d[i][j] == 1 || d[i][j] == -2) {
	      cc->n_CHX++;
	    }
	  }
	}
	else {
	  //CH
	  m[i][j] = CH;
	  cc->n_CH++;
	  if(d[i][j] == 1 || d[i][j] == -2) {
	    cc->n_CHX++;
	  }
	}
      } //end if changeable
      else {
	m[i][j] = NC;
	cc->n_NC++;
      }
    } //end for
}



void diff_map(unsigned char *l, difference_class **m, unsigned int h, unsigned int w) {
  int i, j;
  for(i=0; i<h; ++i)
    for(j=0; j<w; ++j) {
      l[i*w + j] = (m[i][j] == EZ || m[i][j] == EN1);
    }
}

void collect_LSB(
		 unsigned char *lsb,
		 int **d,
		 difference_class **dc,
		 unsigned int h,
		 unsigned int w
		 )
{
  unsigned int i, j, k=0;
  for(i=0; i<h; ++i)
    for(j=0; j<w; ++j) {
      if((dc[i][j] == EN2 || dc[i][j] == CH) && d[i][j] != 1 && d[i][j] != -2)
	lsb[k++] = d[i][j] & 1; //extract lsb
    }
}

void embed(
	   int **h,
	   unsigned int *start_row,
	   unsigned int *start_col,
	   unsigned char *bs,
	   unsigned int n_bs,
	   difference_class **membership,
	   unsigned int width,
	   unsigned int *embedded
	   ) {
  unsigned int i_bs = 0, i = *start_row, j = *start_col;
  unsigned int e=0, c=0;

  while(i_bs < n_bs) {
    if(membership[i][j] == EZ || membership[i][j] == EN1) {
      //expand
      h[i][j] = h[i][j] * 2 + bs[i_bs++];
      ++e;
    }
    else
      if(membership[i][j] == EN2 || membership[i][j] == CH) {
	//change LSB
	h[i][j] = 2 * (int)floor((double)h[i][j] / 2) + bs[i_bs++];
	++c;
      }
    //next difference
    if(j < width - 1)
      //next column
      ++j;
    else {
      //next row
      j = 0;
      ++i;
    }
  }
  *start_row = i;
  *start_col = j;
  *embedded = *embedded + e + c;
}
